# -*- coding: utf-8 -*-
from flask import Flask, request, make_response
from flask_cors import *

import handle_logic
import json
import mongo_
from BoxInit import Box_init
from threading import Thread
import mongo_thread
import argparse
import time

from redis_ import RedisClient

parser = argparse.ArgumentParser()
parser.add_argument('-ip')
parser.add_argument('-P')

args = parser.parse_args()

if args.P:
    RUN1_IP = args.ip
    RUN1_PORT = int(args.P)

else:
    print("请输入 命令行参数 -ip 本机的ip地址 -P 服务器端口号 ")
    RUN1_IP = '192.168.1.12'
    RUN1_PORT = 61002

app = Flask(__name__)
CORS(app, supports_credentials=True)

def mkresp(obj, status_code):
    # 跨域问题
    resp = make_response(json.dumps(obj))
    resp.headers["Access-Control-Allow-Origin"] = "*"
    resp.headers["Access-Control-Allow-Methods"] = "GET,POST"
    resp.headers["Access-Control-Allow-Headers"] = "x-requested-with,content-type"  # 预检请求  该次请求的自定义请求头字段
    return resp, status_code


def to_str(parm):
    if parm is not None:
        parm = str(parm)
    return parm


# 上传至路人库接口
@app.route('/insert_stranger', methods=['POST'])
def insert_stranger():
    try:
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        # face_id 字符串
        id = to_str(json_data.get("id"))
        camera_id = json_data.get("camera_id")
        timestamp = int(json_data.get("timestamp"))
        uri = to_str(json_data.get("uri"))
        face_base64 = to_str(json_data.get("base64"))

        # feature 非必填项
        feature = json_data.get("feature")
        if isinstance(feature, str):
            if len(feature) < 100:
                raise Exception

        if not (isinstance(id, str) and isinstance(camera_id, str) and isinstance(timestamp, int)
                and isinstance(uri, str) and isinstance(face_base64, str)):
            raise Exception

    except Exception:
        return mkresp({"msg": "Parameter error", "rtn": -3}, 6000)
    try:

        if redis_client.llen_name(name) >= 100000:
            raise Exception("requests exceed 100000")

        data = {
            "uri": uri,
            "camera_id": camera_id,
            "face_b64": face_base64,
            "timestamp": timestamp,
            "face_id": id,
            "feature": feature
        }
        redis_client.insert_hit_run1(name, json.dumps(data))

        # is_ok = logic.saving_logic(uri=uri, camera_id=camera_id, face_b64=face_base64, timestamp=timestamp, face_id=id,
        #                            feature=feature)
    except Exception as e:
        return mkresp({"msg": str(e), "rtn": -3}, 417)

    return mkresp({"msg": "OK", "rtn": 0}, 200)
    # if is_ok:
    #     return mkresp({"msg": "OK", "rtn": 0})
    # else:
    #     return mkresp({"msg": "Failed", "rtn": -3})


# 静态库接口
@app.route('/insert_static', methods=['POST'])
def insert_static():
    try:
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        # face_id 字符串
        id = to_str(json_data.get("id"))
        p_name = to_str(json_data.get("name"))
        p_id = to_str(json_data.get("person_id"))
        uri = to_str(json_data.get("uri"))
        face_base64 = to_str(json_data.get("base64"))

        # feature 非必填项
        feature = json_data.get("feature")
        if isinstance(feature, str):
            if len(feature) < 100:
                raise Exception

        if not (isinstance(id, str) and isinstance(p_name, str) and isinstance(p_id, str)
                and isinstance(uri, str) and isinstance(face_base64, str)):
            raise Exception
    except Exception:
        return mkresp({"msg": "Parameter error", "rtn": -3}, 6000)

    try:
        ...
        is_ok = logic.saving_logic_static_repo(id, p_name, p_id, uri, face_base64, feature=feature)
        if is_ok:
            return mkresp({"msg": "OK", "rtn": 0}, 200)
        else:
            return mkresp({"msg": "Failed", "rtn": -3}, 417)
    except Exception as e:
        return mkresp({"msg": str(e), "rtn": -3}, 417)


# 修改静态库接口
@app.route('/change_static', methods=['POST'])
def change_static():
    try:
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        # face_id 字符串
        id = to_str(json_data.get("id"))

        p_name = to_str(json_data.get("name"))
        p_id = to_str(json_data.get("person_id"))
        uri = to_str(json_data.get("uri"))
        feature = json_data.get("feature")
        if isinstance(feature, str):
            if len(feature) < 100:
                raise Exception

        if not (isinstance(id, str)):
            raise Exception
    except Exception:
        return mkresp({"msg": "Parameter error", "rtn": -3}, 6000)

    try:
        ...
        is_ok = logic.change_static_repo(id, feature, p_name, p_id, uri)
        if is_ok:
            return mkresp({"msg": "OK", "rtn": 0}, 200)
        else:
            return mkresp({"msg": "Failed", "rtn": -3}, 417)
    except Exception as e:
        return mkresp({"msg": str(e), "rtn": -3}, 417)


# 删除人像库接口
@app.route('/del_card', methods=['POST'])
def del_card():
    try:
        data = request.get_data()
        json_data = json.loads(data.decode("utf-8"))
        # face_id 字符串
        id_list = json_data.get("id_list")
        if not id_list:
            raise Exception
    except Exception:
        return mkresp({"msg": "Parameter error", "rtn": -3}, 6000)
    try:
        for id in id_list:
            logic.delete_card(str(id))
            # print(res)
        return mkresp({"msg": "OK", "rtn": 0}, 200)
    except Exception as e:
        return mkresp({"msg": str(e), "rtn": -3}, 417)


@app.route('/reset', methods=['GET'])
def reset_box():
    ...
    try:
        box_init = Box_init(m_client=mongo_client, redis_client=redis_client)
        box_init.box_init()
    except Exception as e:
        return mkresp({"msg": str(e), "rtn": -3}, 417)
    else:
        return mkresp({"msg": "OK", "rtn": 0}, 200)


@app.route('/test', methods=['GET'])
def test():
    return mkresp({"msg": "OK", "rtn": 0}, 200)


def init():
    global directory, mongo_host, mongo_port, threshold_f, threshold_c, redis_ip, redis_port, redis_password
    mongo_host = mongoinfo['ip']
    mongo_port = mongoinfo['port']
    threshold_f = guidanginfo['face_similarity']
    threshold_c = guidanginfo['card_similarity']
    redis_ip = redisinfo['ip']
    redis_port = redisinfo['port']
    redis_password = redisinfo['password']
    stranger_limit = guidanginfo['face_limit']
    card_limit = guidanginfo['card_limit']

    # 初始化操作类对象
    global logic, redis_client, name, mongo_client

    mongo_client = mongo_.MyMongoClient(host=mongo_host, port=mongo_port, server_port=RUN1_PORT, ip=RUN1_IP)

    name = 'run1_%s' % (RUN1_PORT)
    redis_client = RedisClient(redis_ip, redis_port, redis_password)

    logic = handle_logic.Logic(m_client=mongo_client, threshold_f=threshold_f,
                               threshold_c=threshold_c, redis_client=redis_client, card_limit=card_limit,
                               stranger_limit=stranger_limit, server_port=RUN1_PORT)

    # 线程 监听请求路人
    def run1_redis():
        while True:
            try:
                new_time = time.time()
                json_data = redis_client.pop_hit_rin1(name)
                if json_data is None:
                    # print("json_data is empty")
                    time.sleep(1)
                    continue
                j = json.loads(json_data)
                uri = j.get("uri")
                camera_id = j.get("camera_id")
                face_b64 = j.get("face_b64")
                timestamp = j.get("timestamp")
                face_id = j.get("face_id")
                feature = j.get("feature")
                is_ok = logic.saving_logic(uri=uri, camera_id=camera_id, face_b64=face_b64, timestamp=timestamp,
                                           face_id=face_id, feature=feature)
                # print("is_ok", is_ok)
                print(time.time() - new_time)

            except Exception as e:
                print(e)

    listener_run1 = Thread(target=run1_redis, args=(), daemon=True)
    listener_run1.start()

    # 线程 监听 Mongo 插入建档库
    listener = Thread(target=mongo_thread.loops,
                      args=(mongo_client, redis_client, 10), daemon=True)
    listener.start()


if __name__ == '__main__':
    with open('../config.py', 'r', encoding="utf-8") as conf_r:
        exec(conf_r.read())
    init()
    app.run(host="0.0.0.0", debug=False, port=RUN1_PORT)
